package cn.kailangtu.serialutils.api;

import android.os.SystemClock;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.LinkedBlockingQueue;

import android_serialport_api.SerialPort;
import cn.kailangtu.commontools.CommonUtils;
import cn.kailangtu.serialutils.modbus.ModbusRtuValidator;

public class SerialPortApi485Temperature {

    private static String TAG = "SerialPortApi==>";
    private String portName;
    private int baudrate;
    private int flags;
    private LinkedBlockingQueue<String> reportMsgQueue = null;
    private LinkedBlockingQueue<String> sendMsgQueue = null;

    private  OutputStream os;
    private  InputStream is;
    private  SerialPort serial;
    private  int resultSize;

    private  byte[] rxByteArray;

    private ReceiveMsgListenerV2 listener;
    private  boolean isReading = false;

    private ComBase comBase;


    public SerialPortApi485Temperature(ComBase comBase){
        reportMsgQueue = new LinkedBlockingQueue<>(500);
        sendMsgQueue = new LinkedBlockingQueue<>(500);
        this.comBase = comBase;
        spy();
    }


    /***
     * 打开串口
     * @param portName 串口名称，例：/dev/ttyS1
     * @param baudrate 波特率
     * @param flags flag
     * @return
     */
    public boolean openSerialPort(String portName,int baudrate,int flags)
    {

        try {
            Log.d("openSerialPortTemp","PORTNAME:"+portName+" ||| BAUDRATE:"+baudrate + " ||| "+flags);
            lastReceiveTime = System.currentTimeMillis();
            this.portName = portName;
            this.baudrate = baudrate;
            this.flags = flags;

            serial = new SerialPort(new File(portName), baudrate, flags);
            os = serial.getOutputStream();
            is = serial.getInputStream();


           // SendThread sendThread =new SendThread();
           // sendThread.start();

//            ProcessThread processThread = new ProcessThread();
//            processThread.start();

            ReadThread();

            Log.d("openSerialPortTemp","打开成功");
            return true;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return false;
    }

    public void close(){
        serial.close();

    }


    public byte[] sendAndReceive(byte[] data,int length)
    {
        try {
            rxByteArray = null;
            resultSize = 0;
            os.write(data);
            os.flush();
            int i =0;
            while(i < 200)
            {

                SystemClock.sleep(5);

                if(isCompleteModbus(length))
                {
                    i = 2000;
                    return rxByteArray;
                }


                i++;
            }
            rxByteArray = null;
            resultSize = 0;


        } catch (IOException e) {
            e.printStackTrace();
        } catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }




    private  boolean onDataReceived(byte[] paramArrayOfByte,
                                       int paramInt) throws ModbusError {

        lastReceiveTime = System.currentTimeMillis();
        rxByteArray = CommonUtils.ArrayAppend(rxByteArray, paramArrayOfByte, paramInt);
        Log.d("DiffTime,COM2","RECEIVE:"+CommonUtils.ByteArrayToHexString(rxByteArray));
        if (rxByteArray == null) {
            return false;
        }
        resultSize += paramInt;
        return false;
    }

    boolean isOpenReadThread = false;
    public void ReadThread()
    {
        if(!isOpenReadThread) {
            isOpenReadThread = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(isOpenReadThread)
                    {
                        try {
                            byte[] buffer = new byte[2048];
                            if (is == null) {
                                return;
                            }
                            SystemClock.sleep(1);
                            int tempSize;
                            tempSize = is.read(buffer);
                            if (tempSize > 0) {
                                onDataReceived(buffer, tempSize);
                            }
                        } catch (IOException e) {
                            //Log.e(TAG, "ReadThread3异常");
                            e.printStackTrace();
                            return;
                        } catch (ModbusError e) {
                            throw new RuntimeException(e);
                        }
                    }
                    isOpenReadThread = false;

                }
            }).start();
        }
    }

    private boolean isCompleteModbus(int length){
        if(rxByteArray != null) {

            if(length > 0)
            {
                if(rxByteArray.length < length)
                {
                    return false;
                }
            }
            boolean check =  ModbusRtuValidator.isCompleteModbusFrame(rxByteArray);
            if(check)
            {
                return true;
            }
            else
            {
                if(rxByteArray.length> 3)
                {
                    if(rxByteArray[1] == 3)
                    {
                        int frameLength = rxByteArray[2];
                        if(rxByteArray.length >= (frameLength+5))
                        {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }




    public void addSendString(String sendString)
    {
        sendMsgQueue.offer(sendString);
    }

    long lastReceiveTime = System.currentTimeMillis();
    public void spy(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    if(System.currentTimeMillis() - lastReceiveTime > 5000)
                    {
                        reopen();
                    }


                    SystemClock.sleep(1000);
                }
            }
        }).start();
    }

    private void reopen()
    {
        try{
            serial.close();
        }
        catch(Exception e)
        {}
        openSerialPort(this.portName,this.baudrate,this.flags);
    }

}
